﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TraceHelper.cs" company="AzureContrib (Open source library http://azurecontrib.codeplex.com)">
//   Microsoft Public License (Ms-PL)
// </copyright>
// <summary>
//   A small helper class
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using AzureContrib.WindowsAzure.Properties;

namespace AzureContrib.WindowsAzure.Diagnostics
{
	/// <summary>
	/// A small helper class
	/// </summary>
	public static class TraceHelper
	{
		/// <summary>
		/// Trace a <see cref="LogLevel.Warning"/> message if the configurationsetting <paramref name="missingConfigurationSetting"/> cannot be found. Activation of <paramref name="typeToActivate"/> fails.
		/// </summary>
		/// <param name="missingConfigurationSetting">The name of the missing configuration setting.</param>
		/// <param name="typeToActivate">The type that failed to activate.</param>
		[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "1", Justification = "AzureContrib.WindowsAzure.Core.Assumes.NotNull handles null checking.")]
		public static void ConfigurationWarning(string missingConfigurationSetting, Type typeToActivate)
		{
			Assumes.NotNull(typeToActivate, "typeToActivate");
			System.Diagnostics.Trace.WriteLine(Strings.ConfigurationSettingNotPresent.F(missingConfigurationSetting, typeToActivate.FullName), LogLevel.Warning.ToString());
		}

		/// <summary>
		/// Add one instance of the supplied <see cref="System.Diagnostics.TraceListener"/> T unless one is allready added.
		/// </summary>
		/// <typeparam name="T">
		/// The type of <see cref="System.Diagnostics.TraceListener"/> to add.
		/// </typeparam>
		/// <returns>
		/// The add one listener.
		/// </returns>
		public static T AddOneListener<T>() where T : System.Diagnostics.TraceListener, new()
		{
			if (System.Diagnostics.Trace.Listeners.EnumerableAny<System.Diagnostics.TraceListener>(tl => tl is T))
			{
				return (T)System.Diagnostics.Trace.Listeners.ToTypedEnumerable<System.Diagnostics.TraceListener>().First(tl => tl is T);
			}

			var t = new T();
			System.Diagnostics.Trace.Listeners.Add(t);
			return t;
		}

		/// <summary>
		/// Remove any <see cref="System.Diagnostics.TraceListener"/> of type <paramref name="type"/> from <see cref="System.Diagnostics.Trace.Listeners"/>.
		/// </summary>
		/// <param name="type">
		/// The type of <see cref="System.Diagnostics.TraceListener"/> to remove.
		/// </param>
		public static void RemoveOfType(Type type)
		{
			// Short cirquit deferred execution.
			var traceListenersToRemove = System.Diagnostics.Trace
				.Listeners
				.Cast<System.Diagnostics.TraceListener>()
				.Where(l => l.GetType() == type)
				.ToArray();

			foreach (var traceListener in traceListenersToRemove)
			{
				System.Diagnostics.Trace.Listeners.Remove(traceListener);
			}
		}
	}
}